package com.example.db2dm.service;

import com.example.db2dm.config.MigrationProperties;
import com.example.db2dm.config.DatabaseConfig;
import com.example.db2dm.entity.MigrationResult;
import com.example.db2dm.entity.MigrationStatus;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.FileWriter;
import java.io.IOException;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Statement;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
public class MigrationServiceImpl implements MigrationService {
    
    private static final Logger logger = LoggerFactory.getLogger(MigrationServiceImpl.class);
    
    @Autowired
    private MigrationProperties migrationProperties;
    
    @Autowired
    private DatabaseConfig databaseConfig;
    
    @Override
    public List<MigrationResult> migrate() {
        logger.info("开始执行数据迁移任务");
        List<MigrationResult> results = new ArrayList<>();
        
        Connection sourceConnection = null;
        Connection targetConnection = null;
        
        try {
            // 建立数据库连接
            sourceConnection = databaseConfig.createSourceConnection();
            targetConnection = databaseConfig.createTargetConnection();
            
            // 获取需要迁移的表列表
            List<String> tablesToMigrate = getTablesToMigrate(sourceConnection);
            logger.info("需要迁移的表数量: {}", tablesToMigrate.size());
            
            // 迁移每张表
            for (String tableName : tablesToMigrate) {
                try {
                    MigrationResult result = migrateTable(sourceConnection, targetConnection, tableName);
                    results.add(result);
                } catch (Exception e) {
                    logger.error("迁移表 {} 时发生未预期错误: {}", tableName, e.getMessage(), e);
                    MigrationResult result = new MigrationResult(tableName);
                    result.setStatus(MigrationStatus.FAILED);
                    result.setErrorMessage(e.getMessage());
                    results.add(result);
                    // 继续处理下一个表
                    continue;
                }
            }
        } catch (Exception e) {
            logger.error("建立数据库连接时发生错误: {}", e.getMessage(), e);
            // 添加一个全局错误结果
            MigrationResult result = new MigrationResult("GLOBAL_CONNECTION");
            result.setStatus(MigrationStatus.FAILED);
            result.setErrorMessage("无法连接到数据库: " + e.getMessage());
            results.add(result);
        } finally {
            // 关闭数据库连接
            try {
                if (sourceConnection != null && !sourceConnection.isClosed()) {
                    sourceConnection.close();
                }
                if (targetConnection != null && !targetConnection.isClosed()) {
                    targetConnection.close();
                }
            } catch (SQLException e) {
                logger.warn("关闭数据库连接时发生错误: {}", e.getMessage(), e);
            }
        }
        
        // 输出迁移报告
        generateMigrationReport(results);
        
        return results;
    }
    
    @Override
    public MigrationResult migrateTable(String tableName) {
        // 此方法需要连接参数，我们将其重载
        throw new UnsupportedOperationException("请使用 migrateTable(Connection source, Connection target, String tableName) 方法");
    }
    
    public MigrationResult migrateTable(Connection sourceConnection, Connection targetConnection, String tableName) {
        logger.info("开始迁移表: {}", tableName);
        MigrationResult result = new MigrationResult(tableName);
        long startTime = System.currentTimeMillis();
        
        try {
            // 检查表是否存在
            boolean sourceExists = isTableExists(sourceConnection, tableName);
            boolean targetExists = isTableExists(targetConnection, tableName);
            
            if (!sourceExists || !targetExists) {
                result.setStatus(MigrationStatus.IGNORED);
                result.setErrorMessage("源表或目标表不存在");
                logger.warn("表 {} 被忽略: 源表存在={}，目标表存在={}", tableName, sourceExists, targetExists);
                return result;
            }
            
            // 检查表结构是否一致（简化实现）
            if (!isTableStructureConsistent(sourceConnection, targetConnection, tableName)) {
                result.setStatus(MigrationStatus.IGNORED);
                result.setErrorMessage("源表和目标表结构不一致");
                logger.warn("表 {} 被忽略: 源表和目标表结构不一致", tableName);
                return result;
            }
            
            // 检查源表和目标表的列数量是否一致
            Map<String, Object> columnCountInfo = checkColumnCountConsistency(sourceConnection, targetConnection, tableName);
            Boolean consistent = (Boolean) columnCountInfo.get("consistent");
            Integer sourceColumnCount = (Integer) columnCountInfo.get("sourceColumnCount");
            Integer targetColumnCount = (Integer) columnCountInfo.get("targetColumnCount");
            
            result.setColumnCountConsistent(consistent);
            result.setSourceColumnCount(sourceColumnCount);
            result.setTargetColumnCount(targetColumnCount);
            
            // 执行数据迁移
            long recordCount = performDataMigration(sourceConnection, targetConnection, tableName);
            
            result.setStatus(MigrationStatus.SUCCESS);
            result.setRecordCount(recordCount);
            logger.info("表 {} 迁移成功，共迁移 {} 条记录", tableName, recordCount);
        } catch (Exception e) {
            result.setStatus(MigrationStatus.FAILED);
            result.setErrorMessage(e.getMessage());
            logger.error("表 {} 迁移失败: {}", tableName, e.getMessage(), e);
            // 根据需求，这里记录错误日志后会返回结果，外层会继续处理下一个表
        } finally {
            long endTime = System.currentTimeMillis();
            result.setDuration(endTime - startTime);
        }
        
        return result;
    }
    
    private List<String> getTablesToMigrate(Connection connection) throws SQLException {
        List<String> allTables = getAllTableNames(connection);
        List<String> specifiedTables = migrationProperties.getTables();
        List<String> excludeTables = migrationProperties.getExcludeTables();

        // 如果配置了特定表，则只迁移这些表（忽略大小写匹配）
        if (specifiedTables != null && !specifiedTables.isEmpty()) {
            // 创建一个忽略大小写的过滤列表
            List<String> filteredTables = new ArrayList<>();
            for (String table : allTables) {
                for (String specifiedTable : specifiedTables) {
                    if (table.equalsIgnoreCase(specifiedTable)) {
                        filteredTables.add(table);
                        break;
                    }
                }
            }
            allTables = filteredTables;
        }
        
        // 移除排除的表（忽略大小写匹配）
        if (excludeTables != null && !excludeTables.isEmpty()) {
            // 创建一个忽略大小写的排除列表
            List<String> filteredTables = new ArrayList<>();
            for (String table : allTables) {
                boolean shouldExclude = false;
                for (String excludeTable : excludeTables) {
                    if (table.equalsIgnoreCase(excludeTable)) {
                        shouldExclude = true;
                        break;
                    }
                }
                if (!shouldExclude) {
                    filteredTables.add(table);
                }
            }
            allTables = filteredTables;
        }
        
        return allTables;
    }
    
    private List<String> getAllTableNames(Connection connection) throws SQLException {
        List<String> tableNames = new ArrayList<>();
        DatabaseMetaData metaData = connection.getMetaData();
        try (ResultSet rs = metaData.getTables(null, null, null, new String[]{"TABLE"})) {
            while (rs.next()) {
                tableNames.add(rs.getString("TABLE_NAME"));
            }
        }
        return tableNames;
    }
    
    private boolean isTableExists(Connection connection, String tableName) {
        try {
            DatabaseMetaData metaData = connection.getMetaData();
            try (ResultSet rs = metaData.getTables(null, null, "%", new String[]{"TABLE"})) {
                while (rs.next()) {
                    String dbTableName = rs.getString("TABLE_NAME");
                    if (dbTableName.equalsIgnoreCase(tableName)) {
                        return true;
                    }
                }
                return false;
            }
        } catch (SQLException e) {
            logger.error("检查表 {} 是否存在时发生错误: {}", tableName, e.getMessage(), e);
            return false;
        }
    }
    
    private boolean isTableStructureConsistent(Connection sourceConnection, Connection targetConnection, String tableName) {
        // 简化实现，实际项目中需要详细比较表结构
        // 这里我们假设结构一致
        return true;
    }
    
    /**
     * 检查源表和目标表的列数量是否一致
     * @param sourceConnection 源数据库连接
     * @param targetConnection 目标数据库连接
     * @param tableName 表名
     * @return 包含列数量信息的Map，包含sourceColumnCount、targetColumnCount和consistent三个键
     */
    private Map<String, Object> checkColumnCountConsistency(Connection sourceConnection, Connection targetConnection, String tableName) {
        Map<String, Object> result = new HashMap<>();
        try {
            // 获取源表列数
            int sourceColumnCount = 0;
            String actualSourceTableName = findActualTableName(sourceConnection, tableName);
            if (actualSourceTableName != null) {
                try (Statement sourceStmt = sourceConnection.createStatement();
                     ResultSet sourceRs = sourceStmt.executeQuery("SELECT * FROM " + actualSourceTableName + " WHERE 1=0")) {
                    sourceColumnCount = sourceRs.getMetaData().getColumnCount();
                }
            } else {
                logger.warn("在源数据库中未找到表: {}", tableName);
            }
            
            // 获取目标表列数
            int targetColumnCount = 0;
            String actualTargetTableName = findActualTableName(targetConnection, tableName);
            if (actualTargetTableName != null) {
                try (Statement targetStmt = targetConnection.createStatement();
                     ResultSet targetRs = targetStmt.executeQuery("SELECT * FROM " + actualTargetTableName + " WHERE 1=0")) {
                    targetColumnCount = targetRs.getMetaData().getColumnCount();
                }
            } else {
                logger.warn("在目标数据库中未找到表: {}", tableName);
            }
            
            // 保存结果
            result.put("sourceColumnCount", sourceColumnCount);
            result.put("targetColumnCount", targetColumnCount);
            result.put("consistent", sourceColumnCount == targetColumnCount);
            
            // 比较列数
            if (sourceColumnCount != targetColumnCount) {
                logger.warn("表 {} 的列数量不一致: 源表 {} 列，目标表 {} 列", tableName, sourceColumnCount, targetColumnCount);
            } else {
                logger.debug("表 {} 的列数量一致: {} 列", tableName, sourceColumnCount);
            }
            
        } catch (SQLException e) {
            logger.warn("检查表 {} 列数量时发生错误: {}", tableName, e.getMessage());
            // 发生异常时，我们仍然继续执行数据迁移
            result.put("sourceColumnCount", null);
            result.put("targetColumnCount", null);
            result.put("consistent", true); // 出错时默认为一致，以保证迁移继续进行
        }
        
        return result;
    }
    
    /**
     * 在数据库中查找实际的表名（忽略大小写）
     * @param connection 数据库连接
     * @param tableName 查找的表名
     * @return 实际的表名，如果未找到则返回null
     */
    private String findActualTableName(Connection connection, String tableName) {
        try {
            DatabaseMetaData metaData = connection.getMetaData();
            try (ResultSet rs = metaData.getTables(null, null, "%", new String[]{"TABLE"})) {
                while (rs.next()) {
                    String dbTableName = rs.getString("TABLE_NAME");
                    if (dbTableName.equalsIgnoreCase(tableName)) {
                        return dbTableName;
                    }
                }
            }
        } catch (SQLException e) {
            logger.warn("查找表 {} 时发生错误: {}", tableName, e.getMessage());
        }
        return null;
    }
    
    private long performDataMigration(Connection sourceConnection, Connection targetConnection, String tableName) throws SQLException {
        long recordCount = 0;
        long batchCount = 0;
        long totalRecords = 0;
        long totalBatches = 0;
        
        // 查找实际的表名
        String actualSourceTableName = findActualTableName(sourceConnection, tableName);
        String actualTargetTableName = findActualTableName(targetConnection, tableName);
        
        if (actualSourceTableName == null) {
            throw new SQLException("在源数据库中找不到表: " + tableName);
        }
        
        if (actualTargetTableName == null) {
            throw new SQLException("在目标数据库中找不到表: " + tableName);
        }
        
        // 清空目标表数据
        try (Statement targetStmt = targetConnection.createStatement()) {
            targetStmt.execute("DELETE FROM " + actualTargetTableName);
        }
        
        // 获取总记录数
        try (Statement sourceStmt = sourceConnection.createStatement();
             ResultSet rs = sourceStmt.executeQuery("SELECT COUNT(*) FROM " + actualSourceTableName);
             ) {
             if (rs.next()) {
                 totalRecords = rs.getLong(1);
                 // 计算总批次数
                 totalBatches = (totalRecords + migrationProperties.getBatchSize() - 1) / migrationProperties.getBatchSize();
             }
        } catch (SQLException e) {
            logger.warn("无法获取表 {} 的总记录数: {}", tableName, e.getMessage());
        }
        
        // 从源表读取数据并插入到目标表
        try (Statement sourceStmt = sourceConnection.createStatement();
             ResultSet rs = sourceStmt.executeQuery("SELECT * FROM " + actualSourceTableName);
             ) {
            
            ResultSetMetaData metaData = rs.getMetaData();
            int columnCount = metaData.getColumnCount();
            
            // 获取列名列表
            List<String> columnNames = new ArrayList<>();
            for (int i = 1; i <= columnCount; i++) {
                columnNames.add(metaData.getColumnName(i));
            }
            
            // 构建预编译SQL语句，显式指定列名
            StringBuilder sqlBuilder = new StringBuilder("INSERT INTO " + actualTargetTableName + " (");
            for (int i = 0; i < columnCount; i++) {
                if (i > 0) sqlBuilder.append(", ");
                sqlBuilder.append(columnNames.get(i));
            }
            sqlBuilder.append(") VALUES (");
            for (int i = 1; i <= columnCount; i++) {
                if (i > 1) sqlBuilder.append(", ");
                sqlBuilder.append("?");
            }
            sqlBuilder.append(")");
            
            String insertSQL = sqlBuilder.toString();
            try (PreparedStatement targetStmt = targetConnection.prepareStatement(insertSQL)) {
                // 用于记录当前批处理的参数值，以便在出错时输出
                List<Object[]> batchParameterValues = new ArrayList<>();
                // 获取目标表各列的最大长度
                int[] targetColumnMaxLengths = getTargetTableColumnLengths(targetConnection, actualTargetTableName, columnNames);
                
                while (rs.next()) {
                    // 设置每个参数的值
                    Object[] currentRowValues = new Object[columnCount];
                    for (int i = 1; i <= columnCount; i++) {
                        Object value = rs.getObject(i);
                        // 保存转换前的值用于日志记录
                        currentRowValues[i-1] = value;
                        
                        // 处理特定的数据类型以确保达梦数据库兼容性
                        if (value == null) {
                            // 明确处理null值，使用最安全的方式
                            targetStmt.setNull(i, java.sql.Types.NULL);
                        } else {
                            // 对于非null值，先尝试类型转换
                            try {
                                int maxLength = targetColumnMaxLengths[i-1];
                                
                                // 转换值以确保与达梦数据库兼容
                                Object compatibleValue = convertToDmCompatibleType(value);
                                // 使用转换后的值进行日志记录
                                currentRowValues[i-1] = compatibleValue;
                                setValueSafely(targetStmt, i, compatibleValue, maxLength);
                            } catch (Exception e) {
                                //logger.warn("设置参数 {} 时发生错误: {}", i, e.getMessage());
                                // 最后的回退机制
                                targetStmt.setNull(i, java.sql.Types.NULL);
                            }
                        }
                    }
                    
                    batchParameterValues.add(currentRowValues);
                    targetStmt.addBatch();
                    recordCount++;
                    
                    // 批量提交
                    if (recordCount % migrationProperties.getBatchSize() == 0) {
                        try {
                            targetStmt.executeBatch();
                            targetStmt.clearBatch();
                            batchParameterValues.clear(); // 清空已成功处理的参数值
                            batchCount++;
                            logger.debug("表 {} 批次 {} / {} 执行完成，已处理 {} / {} 条记录", 
                                tableName, batchCount, totalBatches, recordCount, totalRecords);
                        } catch (SQLException e) {
                            logger.error("执行批处理时发生错误: {}", e.getMessage(), e);
                            logger.error("错误的SQL语句: {}", insertSQL);
                            logBatchParameterValues(batchParameterValues, tableName, columnNames, targetColumnMaxLengths);
                            // 根据新需求，出现错误应该停止此表的导入
                            throw new SQLException("表 " + tableName + " 批处理执行失败，已终止该表迁移，错误信息: " + e.getMessage(), e);
                        }
                    }
                }
                
                // 执行剩余的批次
                try {
                    targetStmt.executeBatch();
                    if (recordCount > 0 && recordCount % migrationProperties.getBatchSize() != 0) {
                        batchCount++;
                    }
                    logger.debug("表 {} 批次 {} / {} 执行完成，已处理 {} / {} 条记录", 
                        tableName, batchCount, totalBatches, recordCount, totalRecords);
                } catch (SQLException e) {
                    logger.error("执行最后批处理时发生错误: {}", e.getMessage(), e);
                    logger.error("错误的SQL语句: {}", insertSQL);
                    logBatchParameterValues(batchParameterValues, tableName, columnNames, targetColumnMaxLengths);
                    // 根据新需求，出现错误应该停止此表的导入
                    throw new SQLException("表 " + tableName + " 最后批处理执行失败，已终止该表迁移，错误信息: " + e.getMessage(), e);
                }
            }
        }
        
        logger.info("表 {} 数据迁移完成，总共处理 {} 条记录，共 {} 个批次", tableName, recordCount, batchCount);
        return recordCount;
    }
    
    /**
     * 获取目标表各列的最大长度
     * @param targetConnection 目标数据库连接
     * @param tableName 表名
     * @param columnNames 列名列表
     * @return 各列最大长度数组，按columnNames顺序排列
     */
    private int[] getTargetTableColumnLengths(Connection targetConnection, String tableName, List<String> columnNames) {
        int[] targetColumnMaxLengths = new int[columnNames.size()];
        
        try {
            // 查找实际的表名
            String actualTableName = findActualTableName(targetConnection, tableName);
            if (actualTableName == null) {
                logger.warn("在目标数据库中找不到表: {}", tableName);
                // 出错时所有列都设置为不限制长度
                for (int i = 0; i < targetColumnMaxLengths.length; i++) {
                    targetColumnMaxLengths[i] = 0;
                }
                return targetColumnMaxLengths;
            }
            
            // 构造查询语句，只查询一条空记录以获取元数据
            StringBuilder sqlBuilder = new StringBuilder("SELECT ");
            for (int i = 0; i < columnNames.size(); i++) {
                if (i > 0) sqlBuilder.append(", ");
                sqlBuilder.append(columnNames.get(i));
            }
            sqlBuilder.append(" FROM ").append(actualTableName).append(" WHERE 1=0");
            
            try (PreparedStatement ps = targetConnection.prepareStatement(sqlBuilder.toString())) {
                ResultSetMetaData metaData = ps.getMetaData();
                
                // 根据列名查找对应的列信息
                for (int i = 0; i < columnNames.size(); i++) {
                    String columnName = columnNames.get(i);
                    targetColumnMaxLengths[i] = 0; // 默认不限制长度
                    
                    // 在元数据中查找对应列名的列
                    for (int j = 1; j <= metaData.getColumnCount(); j++) {
                        if (columnName.equalsIgnoreCase(metaData.getColumnName(j))) {
                            try {
                                int displaySize = metaData.getColumnDisplaySize(j);
                                // 对于TEXT等不限长度的类型，getColumnDisplaySize可能返回0或一个很大的数
                                // 我们将其设置为0表示不限制长度
                                if (displaySize > 1000000) { // 达梦数据库中TEXT等大字段可能返回很大的值
                                    targetColumnMaxLengths[i] = 0;
                                } else if (displaySize > 0) {
                                    targetColumnMaxLengths[i] = displaySize;
                                }
                                break; // 找到匹配的列后跳出循环
                            } catch (SQLException e) {
                                logger.warn("获取目标表 {} 列 {} 的显示大小时出错: {}", tableName, columnName, e.getMessage());
                            }
                        }
                    }
                }
            }
        } catch (SQLException e) {
            logger.warn("获取目标表 {} 元数据时出错: {}", tableName, e.getMessage());
            // 出错时所有列都设置为不限制长度
            for (int i = 0; i < targetColumnMaxLengths.length; i++) {
                targetColumnMaxLengths[i] = 0;
            }
        }
        
        return targetColumnMaxLengths;
    }
    
    /**
     * 获取目标表各列的最大长度（旧版本，为保持向后兼容）
     * @param targetConnection 目标数据库连接
     * @param tableName 表名
     * @param columnCount 列数量
     * @return 各列最大长度数组
     */
    private int[] getTargetTableColumnLengths(Connection targetConnection, String tableName, int columnCount) {
        int[] targetColumnMaxLengths = new int[columnCount];
        for (int i = 0; i < columnCount; i++) {
            // 默认设置为0，表示不限制长度
            targetColumnMaxLengths[i] = 0;
        }
        
        logger.debug("使用旧版本getTargetTableColumnLengths方法，所有列长度默认为0");
        
        return targetColumnMaxLengths;
    }
    
    /**
     * 记录批处理参数值，用于错误诊断
     * @param batchParameterValues 批处理参数值列表
     * @param tableName 表名
     * @param columnNames 列名列表
     * @param targetColumnMaxLengths 目标表各列的最大长度
     */
    private void logBatchParameterValues(List<Object[]> batchParameterValues, String tableName, List<String> columnNames, int[] targetColumnMaxLengths) {
        logger.error("表 {} 批处理参数值详情:", tableName);
        for (int i = 0; i < batchParameterValues.size(); i++) {
            Object[] rowValues = batchParameterValues.get(i);
            logger.error("第 {} 行数据: {}", i+1, java.util.Arrays.toString(rowValues));
            for (int j = 0; j < rowValues.length; j++) {
                Object value = rowValues[j];
                String columnName = j < columnNames.size() ? columnNames.get(j) : "未知列";
                int targetMaxLength = j < targetColumnMaxLengths.length ? targetColumnMaxLengths[j] : 0;
                if (value != null) {
                    String stringValue = value.toString();
                    // 对于CLOB等特殊类型，获取其字符串表示形式的长度
                    int length = stringValue != null ? stringValue.length() : 0;
                    logger.error("  列[{}] 参数[{}]: 类型={}, 值={}, 长度={}, 目标字段最大长度={}", 
                        columnName,
                        j+1, 
                        value.getClass().getSimpleName(), 
                        stringValue, 
                        length,
                        targetMaxLength);
                } else {
                    logger.error("  列[{}] 参数[{}]: null, 目标字段最大长度={}", columnName, j+1, targetMaxLength);
                }
            }
        }
    }
    
    // 重载旧方法以保持向后兼容
    private void logBatchParameterValues(List<Object[]> batchParameterValues, String tableName) {
        int[] emptyMaxLengths = new int[batchParameterValues.isEmpty() ? 0 : batchParameterValues.get(0).length];
        List<String> emptyColumnNames = new ArrayList<>();
        for (int i = 0; i < emptyMaxLengths.length; i++) {
            emptyColumnNames.add("列" + (i + 1));
        }
        logBatchParameterValues(batchParameterValues, tableName, emptyColumnNames, emptyMaxLengths);
    }
    
    /**
     * 重载方法，保持向后兼容
     */
    private void logBatchParameterValues(List<Object[]> batchParameterValues, String tableName, int[] targetColumnMaxLengths) {
        List<String> emptyColumnNames = new ArrayList<>();
        for (int i = 0; i < targetColumnMaxLengths.length; i++) {
            emptyColumnNames.add("列" + (i + 1));
        }
        logBatchParameterValues(batchParameterValues, tableName, emptyColumnNames, targetColumnMaxLengths);
    }
    
    /**
     * 安全地设置参数值，处理达梦数据库的特殊要求
     * @param stmt PreparedStatement
     * @param parameterIndex 参数索引
     * @param value 值
     * @param maxLength 最大长度
     * @throws SQLException SQL异常
     */
    private void setValueSafely(PreparedStatement stmt, int parameterIndex, Object value, int maxLength) throws SQLException {
        if (value == null) {
            stmt.setNull(parameterIndex, java.sql.Types.NULL);
            return;
        }
        
        // 根据值的类型使用特定的setter方法
        if (value instanceof String) {
            String strValue = (String) value;
//            // 检查并处理字符串长度，避免截断错误
//            if (maxLength > 0 && strValue.length() > maxLength) {
//                logger.warn("字符串值长度超过限制，将被截断: 列={}, 原长度={}, 最大长度={}", parameterIndex, strValue.length(), maxLength);
//                strValue = strValue.substring(0, maxLength);
//            }
//            // 再次检查长度，确保不超过安全限制
//            if (strValue.length() > 10000) {
//                logger.warn("字符串值仍然很长，进一步截断到安全长度: 列={}", parameterIndex);
//                strValue = strValue.substring(0, 10000);
//            }
            stmt.setString(parameterIndex, strValue);
        } else if (value instanceof Integer) {
            stmt.setInt(parameterIndex, (Integer) value);
        } else if (value instanceof Long) {
            stmt.setLong(parameterIndex, (Long) value);
        } else if (value instanceof Double) {
            stmt.setDouble(parameterIndex, (Double) value);
        } else if (value instanceof Float) {
            stmt.setFloat(parameterIndex, (Float) value);
        } else if (value instanceof Boolean) {
            stmt.setBoolean(parameterIndex, (Boolean) value);
        } else if (value instanceof java.sql.Date) {
            stmt.setDate(parameterIndex, (java.sql.Date) value);
        } else if (value instanceof java.sql.Timestamp) {
            stmt.setTimestamp(parameterIndex, (java.sql.Timestamp) value);
        } else if (value instanceof java.math.BigDecimal) {
            stmt.setBigDecimal(parameterIndex, (java.math.BigDecimal) value);
        } else {
            // 对于其他类型，使用setObject但捕获可能的异常
            try {
                stmt.setObject(parameterIndex, value);
            } catch (Exception e) {
                logger.warn("使用setObject设置值时出错: {}", e.getMessage());
                // 如果value.toString()可能为null，使用空字符串
                String stringValue = value.toString();
                if (stringValue == null) {
                    stmt.setNull(parameterIndex, java.sql.Types.VARCHAR);
                } else {
                    // 同样检查字符串长度
                    if (maxLength > 0 && stringValue.length() > maxLength) {
                        logger.warn("字符串值长度超过限制，将被截断: 列={}, 原长度={}, 最大长度={}", parameterIndex, stringValue.length(), maxLength);
                        stringValue = stringValue.substring(0, maxLength);
                    }
                    // 再次检查长度，确保不超过安全限制
                    if (stringValue.length() > 10000) {
                        logger.warn("字符串值仍然很长，进一步截断到安全长度: 列={}", parameterIndex);
                        stringValue = stringValue.substring(0, 10000);
                    }
                    stmt.setString(parameterIndex, stringValue);
                }
            }
        }
    }
    
    // 重载方法，保持向后兼容
    private void setValueSafely(PreparedStatement stmt, int parameterIndex, Object value) throws SQLException {
        setValueSafely(stmt, parameterIndex, value, -1);
    }
    
    /**
     * 转换数据类型以确保与达梦数据库兼容
     * @param value 原始值
     * @return 兼容的值
     */
    private Object convertToDmCompatibleType(Object value) {
        if (value == null) {
            return null;
        }
        
        // 处理常见的不兼容类型
        if (value instanceof java.util.Date && !(value instanceof java.sql.Date)) {
            // 将java.util.Date转换为java.sql.Timestamp
            return new java.sql.Timestamp(((java.util.Date) value).getTime());
        } else if (value instanceof java.sql.Clob) {
            // 处理CLOB类型
            try {
                java.sql.Clob clob = (java.sql.Clob) value;
                return clob.getSubString(1, (int) clob.length());
            } catch (SQLException e) {
                logger.warn("处理CLOB类型时出错: {}", e.getMessage());
                return value.toString();
            }
        } else if (value instanceof java.sql.Blob) {
            // 处理BLOB类型，保持原样
            return value;
        } else if (value instanceof oracle.sql.ROWID) {
            // 处理Oracle特定的ROWID类型
            return value.toString();
        } else if (value instanceof oracle.sql.TIMESTAMP) {
            // 处理Oracle特定的时间戳类型
            try {
                oracle.sql.TIMESTAMP ts = (oracle.sql.TIMESTAMP) value;
                return ts.timestampValue();
            } catch (SQLException e) {
                logger.warn("处理Oracle TIMESTAMP类型时出错: {}", e.getMessage());
                return value.toString();
            }
        }
        
        // 对于其他类型，保持原样
        return value;
    }
    
    private void generateMigrationReport(List<MigrationResult> results) {
        logger.info("======= 数据迁移报告 =======");
        long successCount = results.stream().filter(r -> r.getStatus() == MigrationStatus.SUCCESS).count();
        long failedCount = results.stream().filter(r -> r.getStatus() == MigrationStatus.FAILED).count();
        long ignoredCount = results.stream().filter(r -> r.getStatus() == MigrationStatus.IGNORED).count();
        long totalRecords = results.stream().filter(r -> r.getStatus() == MigrationStatus.SUCCESS)
                .mapToLong(MigrationResult::getRecordCount).sum();
        
        logger.info("成功迁移表数量: {}", successCount);
        logger.info("迁移失败表数量: {}", failedCount);
        logger.info("忽略表数量: {}", ignoredCount);
        logger.info("总迁移记录数: {}", totalRecords);
        
        if (failedCount > 0) {
            logger.info("失败详情:");
            results.stream().filter(r -> r.getStatus() == MigrationStatus.FAILED)
                    .forEach(r -> logger.info("- {}: {}", r.getTableName(), r.getErrorMessage()));
        }
        
        // 导出到CSV文件
        exportResultsToCsv(results);
        
        logger.info("======= 报告结束 =======");
    }
    
    /**
     * 将迁移结果导出到CSV文件
     * @param results 迁移结果列表
     */
    private void exportResultsToCsv(List<MigrationResult> results) {
        String fileName = "migration_report_" + LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMdd_HHmmss")) + ".csv";
        String filePath = System.getProperty("user.dir") + "/" + fileName;
        
        try (FileWriter writer = new FileWriter(filePath, true)) {
            // 写入CSV头部
            writer.append("表名,状态,记录数,耗时(毫秒),列数量一致,源表列数,目标表列数,错误信息\n");
            
            // 写入数据行
            for (MigrationResult result : results) {
                writer.append(result.getTableName())
                      .append(",")
                      .append(result.getStatus().toString())
                      .append(",")
                      .append(String.valueOf(result.getRecordCount()))
                      .append(",")
                      .append(String.valueOf(result.getDuration()))
                      .append(",")
                      .append(result.getColumnCountConsistent() != null ? result.getColumnCountConsistent().toString() : "N/A")
                      .append(",")
                      .append(result.getSourceColumnCount() != null ? result.getSourceColumnCount().toString() : "N/A")
                      .append(",")
                      .append(result.getTargetColumnCount() != null ? result.getTargetColumnCount().toString() : "N/A")
                      .append(",")
                      .append(result.getErrorMessage() != null ? result.getErrorMessage().replace(",", "，") : "")
                      .append("\n");
            }
            
            logger.info("迁移结果已导出到CSV文件: {}", filePath);
        } catch (IOException e) {
            logger.error("导出CSV文件时发生错误: {}", e.getMessage(), e);
        }
    }
}
